﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Winz.FoeBot;
using Winz.JsonModel;

using System.Data.Entity;

using System.Diagnostics;

namespace Winz.FoeBot.DataLayer
{
    public class FoeDbUpdater
    {
        private JsonParser jsonParser;
        private int userId = 0;

        public FoeDbUpdater(JsonParser jsonParser)
        {
            jsonParser.GameStarted += OnStartupRecieved;
            jsonParser.ResearchRecieved += OnResearchRecieved;
            jsonParser.TradeOffersRecieved += OnTradeOffersRecieved;
        }




        private void UpdtateResource(Resources newResources, Resources existingResources,FoeContext db) {
            newResources.ResourcesId = existingResources.ResourcesId;
            db.Entry(existingResources).CurrentValues.SetValues(newResources);

            foreach (Good g in newResources.Goods)
            {
                g.RessoureId = existingResources.ResourcesId;
                g.Resources = existingResources;
                Good existingGood = db.Goods.Find(existingResources.ResourcesId, g.GoodId);
                if (existingGood == null)
                    existingResources.Goods.Add(g);
                else
                    db.Entry(existingGood).CurrentValues.SetValues(g);
            }

            foreach (Good g in db.Goods.Where(dbg => dbg.RessoureId == existingResources.ResourcesId))
            {
                if (newResources.Goods.FirstOrDefault(ug => ug.GoodId == g.GoodId) == null)
                    g.Value = 0;
            }
        }


        private void OnResearchRecieved(object o, MessageEventArgs<List<Research>> e)
        {
            Debug.Print("Researchs recieved");
            try
            {
                using (var db = new FoeContext())
                {

                    foreach (Research r in e.Message)
                    {
                        Research existingResearch = db.Researchs.Find(r.ResearchId);
                        if (existingResearch == null)
                            db.Researchs.Add(r);


                        if (this.userId != 0)
                        {
                            r.Progress.PlayerId = this.userId;

                            Progress existingProgress = db.ResearchProgress.Find(this.userId, r.Progress.ResearchId);
                            if (existingProgress == null)
                                db.ResearchProgress.Add(r.Progress);
                            else
                                db.Entry(existingProgress).CurrentValues.SetValues(r.Progress);
                        }
                        
                    }

                    


                    int recordsAffected = db.SaveChanges();
                    Debug.Print(
                        "Research : Saved {0} entities to the database",
                        recordsAffected);
                }
            }
            catch (Exception ex)
            {
            }
        }


        private void OnTradeOffersRecieved(object o, MessageEventArgs<List<TradeOffer>> e)
        {
            Debug.Print("TradeOffer recieved");
            try
            {
                using (var db = new FoeContext())
                {


                    // add Trade Offers sent
                    foreach (TradeOffer to in e.Message.Where(to => to.Merchant.IsSelf ?? false))
                    {
                        /*
                        Merchant existingMerchant = db.Merchants.Find(to.Merchant.PlayerId);
                        if (existingMerchant == null)
                        {
                            db.Merchants.Add(to.Merchant);
                        }
                        */
                        
                        TradeOffer existingTradeOffer = db.TradeOffers.Find(to.Id);
                        if (existingTradeOffer == null)
                        {

                            to.PlayerId = to.Merchant.PlayerId;
                                db.TradeOffers.Add(to);
                        }
                        
                    }

                    var listDb = (from to in db.TradeOffers
                                  where to.PlayerId == this.userId
                                  select to).ToList();
                    var listMessage = (from to in e.Message
                                       select to).ToList();

                    //Remove TradeOffers not sent
                    var toRemove = (from to in listDb
                                       where !(from tom in listMessage
                                               select tom.Id).Contains(to.Id)
                                       select to
                    ).ToList();

                    toRemove.ForEach(to => db.TradeOffers.Remove(to));
                    
                    
                    
                    int recordsAffected = db.SaveChanges();
                    Debug.Print(
                        "Research : Saved {0} entities to the database",
                        recordsAffected);
                }
            }
            catch (InvalidOperationException ex)
            {
            }

        }
            
        private void OnStartupRecieved(object o, MessageEventArgs<StartUp> e)
        {

            Debug.Print("Startup recieved");
            this.userId = e.Message.UserData.PlayerId;

            UserData userData = e.Message.UserData;
            userData.Resources = e.Message.Resources;
            try
            {
                using (var db = new FoeContext())
                {
                    int recordsAffected;

                    UserData existingUserData = db.Users.Find(userData.PlayerId);

                    if (existingUserData == null)
                    {
                        db.Users.Add(userData);
                    }
                    else
                    {
                        db.Entry(existingUserData).CurrentValues.SetValues(userData);
                        Resources existingResources = db.Resources.Where(r => r.ResourcesId == existingUserData.Resources.ResourcesId).FirstOrDefault();
                        UpdtateResource(userData.Resources, existingResources, db);
                    }
                    recordsAffected = db.SaveChanges();
                    Debug.Print(
                        "Startup : Saved {0} entities to the database",
                        recordsAffected
                        );


                }
            }
            catch (Exception ex)
            {

            }

        }

        

    }
}
